package com.aihna.mall.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.aihna.common.core.domain.R;
import com.aihna.common.core.exception.ServiceException;
import com.aihna.common.core.utils.MapstructUtils;
import com.aihna.common.core.validate.AddGroup;
import com.aihna.common.core.validate.EditGroup;
import com.aihna.common.excel.utils.ExcelUtil;
import com.aihna.common.idempotent.annotation.RepeatSubmit;
import com.aihna.common.log.annotation.Log;
import com.aihna.common.log.enums.BusinessType;
import com.aihna.common.mybatis.core.page.PageQuery;
import com.aihna.common.mybatis.core.page.TableDataInfo;
import com.aihna.common.web.core.BaseController;
import com.aihna.mall.constants.StoreConstants;
import com.aihna.mall.domain.bo.*;
import com.aihna.mall.domain.vo.StoreProductAttrValueVo;
import com.aihna.mall.domain.vo.StoreProductAttrVo;
import com.aihna.mall.domain.vo.StoreProductInfoVo;
import com.aihna.mall.domain.vo.StoreProductVo;
import com.aihna.mall.service.IStoreProductAttrService;
import com.aihna.mall.service.IStoreProductAttrValueService;
import com.aihna.mall.service.IStoreProductService;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 商品
 *
 * @author Joseph.Chen
 * @date 2024-03-29
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/mall/storeProduct")
public class StoreProductController extends BaseController {

    private final IStoreProductService storeProductService;

    private final IStoreProductAttrService storeProductAttrService;

    private final IStoreProductAttrValueService storeProductAttrValueService;

    private final TransactionTemplate transactionTemplate;

    /**
     * 查询商品列表
     */
    @SaCheckPermission("mall:storeProduct:list")
    @GetMapping("/list")
    public TableDataInfo<StoreProductVo> list(StoreProductBo bo, PageQuery pageQuery) {
        return storeProductService.queryPageList(bo, pageQuery);
    }

    /**
     * 导出商品列表
     */
    @SaCheckPermission("mall:storeProduct:export")
    @Log(title = "商品", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(StoreProductBo bo, HttpServletResponse response) {
        List<StoreProductVo> list = storeProductService.queryList(bo);
        ExcelUtil.exportExcel(list, "商品", StoreProductVo.class, response);
    }

    /**
     * 获取商品详细信息
     *
     * @param id 主键
     */
    @SaCheckPermission("mall:storeProduct:query")
    @GetMapping("/{id}")
    public R<StoreProductInfoVo> getInfo(@NotNull(message = "主键不能为空")
                                     @PathVariable Long id) {
        StoreProductVo storeProductVo = storeProductService.queryById(id);

        if (ObjectUtil.isNull(storeProductVo)) {
            throw new ServiceException("未找到对应商品信息");
        }

        StoreProductInfoVo storeProductInfoVo = MapstructUtils.convert(storeProductVo, StoreProductInfoVo.class);
        // 设置商品所参与的活动
        List<String> activityList = getProductActivityList(storeProductVo.getActivity());
        storeProductInfoVo.setActivityList(activityList);

        //设置属性
        List<StoreProductAttrVo> attrList = storeProductAttrService.getListByProductIdAndType(storeProductVo.getId(), StoreConstants.PRODUCT_TYPE_NORMAL);
        storeProductInfoVo.setAttr(attrList);

        //设置属性值
        List<StoreProductAttrValueVo> attrValueList = storeProductAttrValueService.getListByProductIdAndType(storeProductVo.getId(), StoreConstants.PRODUCT_TYPE_NORMAL);
        storeProductInfoVo.setAttrValue(attrValueList);

        return R.ok(storeProductInfoVo);
    }

    /**
     * 新增商品
     */
    @SaCheckPermission("mall:storeProduct:add")
    @Log(title = "商品", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping()
    public R<Void> add(@Validated(AddGroup.class) @RequestBody StoreProductInfoBo bo) {
        // 多规格需要校验规格参数
        if (ObjectUtil.equals(bo.getSpecType(), 0)) {
            if (bo.getAttrValue().size() > 1) {
                throw new ServiceException("单规格商品属性值不能大于1");
            }
        }

        StoreProductBo storeProductBo = MapstructUtils.convert(bo, StoreProductBo.class);
        // 设置Acticity活动
        storeProductBo.setActivity(getProductActivityStr(bo.getActivityList()));

        List<StoreProductAttrValueBo> attrValueAddRequestList = bo.getAttrValue();
        //计算价格
        StoreProductAttrValueBo minAttrValue = attrValueAddRequestList.stream().min(Comparator.comparing(StoreProductAttrValueBo::getPrice)).get();
        storeProductBo.setPrice(minAttrValue.getPrice());
        storeProductBo.setOtPrice(minAttrValue.getOtPrice());
        storeProductBo.setCostPrice(minAttrValue.getCostPrice());
        storeProductBo.setStock(attrValueAddRequestList.stream().mapToLong(StoreProductAttrValueBo::getStock).sum());

        // 默认值设置
        if (ObjectUtil.isNull(bo.getSort())) {
            storeProductBo.setSort(0L);
        }
        if (ObjectUtil.isNull(bo.getIsHot())) {
            storeProductBo.setIsHot(0);
        }
        if (ObjectUtil.isNull(bo.getIsBenefit())) {
            storeProductBo.setIsBenefit(0);
        }
        if (ObjectUtil.isNull(bo.getIsBest())) {
            storeProductBo.setIsBest(0);
        }
        if (ObjectUtil.isNull(bo.getIsNew())) {
            storeProductBo.setIsNew(0);
        }
        if (ObjectUtil.isNull(bo.getIsGood())) {
            storeProductBo.setIsGood(0);
        }
        if (ObjectUtil.isNull(bo.getGiveIntegral())) {
            storeProductBo.setGiveIntegral(0L);
        }
        if (ObjectUtil.isNull(bo.getFicti())) {
            storeProductBo.setFicti(0L);
        }

        List<StoreProductAttrBo> addRequestList = bo.getAttr();
        List<StoreProductAttrBo> attrList = addRequestList.stream().map(e -> {
            StoreProductAttrBo attr = new StoreProductAttrBo();
            BeanUtils.copyProperties(e, attr);
            attr.setType(StoreConstants.PRODUCT_TYPE_NORMAL);
            return attr;
        }).collect(Collectors.toList());

        List<StoreProductAttrValueBo> attrValueList = attrValueAddRequestList.stream().map(e -> {
            StoreProductAttrValueBo attrValue = new StoreProductAttrValueBo();
            BeanUtils.copyProperties(e, attrValue);
            attrValue.setId(null);
            attrValue.setSku(getSku(e.getAttrValue()));
            attrValue.setQuota(0L);
            attrValue.setQuotaShow(0L);
            attrValue.setType(StoreConstants.PRODUCT_TYPE_NORMAL);
            attrValue.setImage(e.getImage());
            return attrValue;
        }).collect(Collectors.toList());

        Boolean execute = transactionTemplate.execute(e -> {
            storeProductBo.setVipPrice(storeProductBo.getPrice());
            storeProductService.insertByBo(storeProductBo);

            attrList.forEach(attr -> attr.setProductId(storeProductBo.getId()));
            attrValueList.forEach(value -> value.setProductId(storeProductBo.getId()));


            storeProductAttrService.saveBatch(attrList);
            storeProductAttrValueService.saveBatch(attrValueList);

            return Boolean.TRUE;
        });

        return toAjax(execute);
    }

    /**
     * 修改商品
     */
    @SaCheckPermission("mall:storeProduct:edit")
    @Log(title = "商品", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PutMapping()
    public R<Void> edit(@Validated(EditGroup.class) @RequestBody StoreProductInfoBo bo) {
        if (ObjectUtil.isNull(bo.getId())) {
            throw new ServiceException("商品ID不能为空");
        }

        if (ObjectUtil.equals(bo.getSpecType(), 0)) {
            if (bo.getAttrValue().size() > 1) {
                throw new ServiceException("单规格商品属性值不能大于1");
            }
        }

        StoreProductVo storeProductVo = storeProductService.queryById(bo.getId());

        if (ObjectUtil.isNull(storeProductVo)) {
            throw new ServiceException("商品不存在");
        }

        if (ObjectUtil.equals(storeProductVo.getIsRecycle(), 1)) {
            throw new ServiceException("商品已删除");
        }
        if (ObjectUtil.equals(storeProductVo.getIsShow(), 1)) {
            throw new ServiceException("请先下架商品，再进行修改");
        }

        StoreProductBo storeProductBo = MapstructUtils.convert(bo, StoreProductBo.class);
        // 设置Activity活动
        storeProductBo.setActivity(getProductActivityStr(bo.getActivityList()));

        List<StoreProductAttrValueBo> attrValueAddRequestList = bo.getAttrValue();
        //计算价格
        StoreProductAttrValueBo minAttrValue = attrValueAddRequestList.stream().min(Comparator.comparing(StoreProductAttrValueBo::getPrice)).get();
        storeProductBo.setPrice(minAttrValue.getPrice());
        storeProductBo.setOtPrice(minAttrValue.getOtPrice());
        storeProductBo.setCostPrice(minAttrValue.getCostPrice());
        storeProductBo.setStock(attrValueAddRequestList.stream().mapToLong(StoreProductAttrValueBo::getStock).sum());

        // attr部分
        List<StoreProductAttrBo> addRequestList = bo.getAttr();
        List<StoreProductAttrBo> attrAddList = CollUtil.newArrayList();
        List<StoreProductAttrBo> attrUpdateList = CollUtil.newArrayList();
        addRequestList.forEach(e -> {
            StoreProductAttrBo attr = new StoreProductAttrBo();
            BeanUtils.copyProperties(e, attr);
            if (ObjectUtil.isNull(attr.getId())) {
                attr.setProductId(storeProductBo.getId());
                attr.setType(StoreConstants.PRODUCT_TYPE_NORMAL);
                attrAddList.add(attr);
            } else {
                attr.setId(null);
                attrUpdateList.add(attr);
            }
        });

        // attrValue部分
        List<StoreProductAttrValueBo> attrValueAddList = CollUtil.newArrayList();
        List<StoreProductAttrValueBo> attrValueUpdateList = CollUtil.newArrayList();
        attrValueAddRequestList.forEach(e -> {
            StoreProductAttrValueBo attrValue = new StoreProductAttrValueBo();
            BeanUtils.copyProperties(e, attrValue);
            attrValue.setSku(getSku(e.getAttrValue()));
            attrValue.setImage(e.getImage());
            if (ObjectUtil.isNull(attrValue.getId()) || attrValue.getId().equals(0)) {
                attrValue.setId(null);
                attrValue.setProductId(storeProductBo.getId());
                attrValue.setQuota(0L);
                attrValue.setQuotaShow(0L);
                attrValue.setType(StoreConstants.PRODUCT_TYPE_NORMAL);
                attrValueAddList.add(attrValue);
            } else {
                attrValue.setId(null);
                attrValueUpdateList.add(attrValue);
            }
        });

        Boolean execute = transactionTemplate.execute(e -> {
            storeProductService.updateByBo(storeProductBo);

            // 先删除原用attr+value
            storeProductAttrService.deleteByProductIdAndType(storeProductBo.getId(), StoreConstants.PRODUCT_TYPE_NORMAL);
            storeProductAttrValueService.deleteByProductIdAndType(storeProductBo.getId(), StoreConstants.PRODUCT_TYPE_NORMAL);

            if (CollUtil.isNotEmpty(attrAddList)) {
                storeProductAttrService.saveBatch(attrAddList);
            }
            if (CollUtil.isNotEmpty(attrUpdateList)) {
                storeProductAttrService.saveOrUpdateBatch(attrUpdateList);
            }

            if (CollUtil.isNotEmpty(attrValueAddList)) {
                storeProductAttrValueService.saveBatch(attrValueAddList);
            }
            if (CollUtil.isNotEmpty(attrValueUpdateList)) {
                storeProductAttrValueService.saveOrUpdateBatch(attrValueUpdateList);
            }

            return Boolean.TRUE;
        });

        return toAjax(execute);
    }

    /**
     * 删除商品
     *
     * @param ids 主键串
     */
    @SaCheckPermission("mall:storeProduct:remove")
    @Log(title = "商品", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public R<Void> remove(@NotEmpty(message = "主键不能为空")
                          @PathVariable Long[] ids, @RequestParam(value = "type", required = false, defaultValue = "recycle")String type) {
        //TODO 删除购物车商品

        return toAjax(storeProductService.deleteProduct(ids, type));
    }

    /**
     * 恢复已删除商品表
     * @param ids 主键串
     */
    @SaCheckPermission("mall:storeProduct:edit")
    @Log(title = "商品", businessType = BusinessType.DELETE)
    @GetMapping(value = "/restore/{ids}")
    public R<Void> restore(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) {
        return toAjax(storeProductService.reStoreProduct(ids));
    }

    /**
     * 状态修改
     */
    @SaCheckPermission("mall:storeProductSpu:edit")
    @Log(title = "商品", businessType = BusinessType.UPDATE)
    @PutMapping("/changeStatus")
    public R<Void> changeStatus(@RequestBody StoreProductBo bo) {
        return toAjax(storeProductService.updateStatus(bo.getId(), bo.getIsShow()));
    }

    @GetMapping("/getCount")
    @Log(title = "商品", businessType = BusinessType.UPDATE)
    @SaCheckPermission("mall:storeProductSpu:edit")
    public R<Map<Integer, Long>> getSpuCount() {
        return R.ok(storeProductService.getTabsCount());
    }



    /**
     * 商品活动字符列表
     * @param activityStr 商品活动字符串
     * @return 商品活动字符列表
     */
    private List<String> getProductActivityList(String activityStr) {
        List<String> activityList = CollUtil.newArrayList();
        if ("0, 1, 2, 3".equals(activityStr)) {
            activityList.add(StoreConstants.PRODUCT_TYPE_NORMAL_STR);
            activityList.add(StoreConstants.PRODUCT_TYPE_SECKILL_STR);
            activityList.add(StoreConstants.PRODUCT_TYPE_BARGAIN_STR);
            activityList.add(StoreConstants.PRODUCT_TYPE_PINGTUAN_STR);
            return activityList;
        }
        String[] split = activityStr.split(",");
        for (String s : split) {
            Integer integer = Integer.valueOf(s);
            if (integer.equals(StoreConstants.PRODUCT_TYPE_NORMAL)) {
                activityList.add(StoreConstants.PRODUCT_TYPE_NORMAL_STR);
            }
            if (integer.equals(StoreConstants.PRODUCT_TYPE_SECKILL)) {
                activityList.add(StoreConstants.PRODUCT_TYPE_SECKILL_STR);
            }
            if (integer.equals(StoreConstants.PRODUCT_TYPE_BARGAIN)) {
                activityList.add(StoreConstants.PRODUCT_TYPE_BARGAIN_STR);
            }
            if (integer.equals(StoreConstants.PRODUCT_TYPE_PINGTUAN)) {
                activityList.add(StoreConstants.PRODUCT_TYPE_PINGTUAN_STR);
            }
        }
        return activityList;
    }

    /**
     * 商品活动字符串
     * @param activityList 活动数组
     * @return 商品活动字符串
     */
    private String getProductActivityStr(List<String> activityList) {
        if (CollUtil.isEmpty(activityList)) {
            return "0, 1, 2, 3";
        }
        List<Integer> activities = new ArrayList<>();
        activityList.forEach(e->{
            switch (e) {
                case StoreConstants.PRODUCT_TYPE_NORMAL_STR:
                    activities.add(StoreConstants.PRODUCT_TYPE_NORMAL);
                    break;
                case StoreConstants.PRODUCT_TYPE_SECKILL_STR:
                    activities.add(StoreConstants.PRODUCT_TYPE_SECKILL);
                    break;
                case StoreConstants.PRODUCT_TYPE_BARGAIN_STR:
                    activities.add(StoreConstants.PRODUCT_TYPE_BARGAIN);
                    break;
                case StoreConstants.PRODUCT_TYPE_PINGTUAN_STR:
                    activities.add(StoreConstants.PRODUCT_TYPE_PINGTUAN);
                    break;
            }
        });
        return activities.stream().map(Object::toString).collect(Collectors.joining(","));
    }

    /**
     * 商品sku
     * @param attrValue json字符串
     * @return sku
     */
    private String getSku(String attrValue) {
        LinkedHashMap<String, String> linkedHashMap = JSONObject.parseObject(attrValue, LinkedHashMap.class, Feature.OrderedField);
        Iterator<Map.Entry<String, String>> iterator = linkedHashMap.entrySet().iterator();
        List<String> strings = CollUtil.newArrayList();
        while (iterator.hasNext()) {
            Map.Entry<String, String> next = iterator.next();
            strings.add(next.getValue());
        }
//        List<String> strings = jsonObject.values().stream().map(o -> (String) o).collect(Collectors.toList());
        return String.join(",", strings);
    }
}
